/*
 * listPPD.c
 *
 *  Created on: 11/12/2011
 *      Author: utn_so
 */

#include "listPPD.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "../General/Serializable/serializable.h"
#include <semaphore.h>

void ListPPD_Create(ListPPD * aListPPD)
{
	aListPPD->Head = NULL;
	aListPPD->Tail = NULL;
	aListPPD->count = 0;
	pthread_mutex_init(&(aListPPD->mutex), NULL);
	sem_init(&(aListPPD->semList), 0, 0);
}

void ListPPD_Push(ListPPD * aListPPD, ListPPD_data data)
{
	pthread_mutex_lock(&(aListPPD->mutex));
	Nodo_ListPPD * aux = (Nodo_ListPPD *) malloc(sizeof(Nodo_ListPPD));

	Message_Copy(&(aux->data.msg), data.msg);
	aux->data.socket = data.socket;
	aux->nxt = NULL;

	if (aListPPD->Head == NULL) {
		aListPPD->Head = aux;
		aListPPD->Tail = aux;
	}
	else {
		aListPPD->Tail->nxt = aux;
		aListPPD->Tail = aux;
	}
	aListPPD->count++;
	pthread_mutex_unlock(&(aListPPD->mutex));
	sem_post(&(aListPPD->semList));
}

void ListPPD_Destroy(ListPPD * aListPPD)
{
	Nodo_ListPPD * aux;
	while (aListPPD->Head != NULL) {
		aux = aListPPD->Head;
		aListPPD->Head = aListPPD->Head->nxt;
		free(aux);
	}
	aListPPD->Head = NULL;
	aListPPD->Tail = NULL;
	aListPPD->count = 0;
	pthread_mutex_destroy(&(aListPPD->mutex));
}

Nodo_ListPPD * ListPPD_getAndDisposeFirst(ListPPD * aListPPD)
{
	sem_wait(&(aListPPD->semList));
	pthread_mutex_lock(&(aListPPD->mutex));
	Nodo_ListPPD * Result;
	Result = aListPPD->Head;
	aListPPD->Head = aListPPD->Head->nxt;
	if (aListPPD->Head == NULL)
		aListPPD->Tail = NULL;
	aListPPD->count--;
	pthread_mutex_unlock(&(aListPPD->mutex));
	return Result;
}

void ListPPD_DisposeFirst(ListPPD * aListPPD)
{
	pthread_mutex_lock(&(aListPPD->mutex));
	Nodo_ListPPD * toDelete;
	toDelete = aListPPD->Head;
	if (toDelete != NULL) {
		aListPPD->Head = aListPPD->Head->nxt;
		if (aListPPD->Head == NULL)
			aListPPD->Tail = NULL;
		aListPPD->count--;
		if (toDelete->data.msg.contentSize > 0)
			free(toDelete->data.msg.content);
		free(toDelete);
	}
	pthread_mutex_unlock(&(aListPPD->mutex));
}

void ListPPD_Add(ListPPD * aListPPD, ListPPD_data data)
{
	pthread_mutex_lock(&(aListPPD->mutex));
	Nodo_ListPPD * aux = (Nodo_ListPPD *) malloc(sizeof(Nodo_ListPPD));

	Message_Copy(&(aux->data.msg), data.msg);
	aux->data.socket = data.socket;
	aux->nxt = NULL;

	if (aListPPD->Head == NULL) {
		aListPPD->Head = aux;
		aListPPD->Tail = aux;
	}
	else {
		aListPPD->Tail->nxt = aux;
		aListPPD->Tail = aux;
	}
	aListPPD->count++;
	pthread_mutex_unlock(&(aListPPD->mutex));
}

Nodo_ListPPD * ListPPD_getAndDisposeFirstUnSync(ListPPD * aListPPD)
{
	pthread_mutex_lock(&(aListPPD->mutex));
	Nodo_ListPPD * Result;
	Result = aListPPD->Head;
	aListPPD->Head = aListPPD->Head->nxt;
	if (aListPPD->Head == NULL)
		aListPPD->Tail = NULL;
	aListPPD->count--;
	pthread_mutex_unlock(&(aListPPD->mutex));
	return Result;
}


void nodoListPPD_Free(Nodo_ListPPD * toDelete)
{
	if (toDelete->data.msg.contentSize > 0)
		free(toDelete->data.msg.content);
	free(toDelete);
}
